package top.whysu.edevice.service.app.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.feilong.lib.lang3.StringUtils;
import liquibase.pro.packaged.A;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import top.whysu.edevice.constant.AppConstant;
import top.whysu.edevice.constant.CodeConstant;
import top.whysu.edevice.constant.DataDictionary;
import top.whysu.edevice.dao.manage.ManageVoucherDao;
import top.whysu.edevice.dao.relative.RelativeVoucherAccountDao;
import top.whysu.edevice.dao.system.AccountDao;
import top.whysu.edevice.dto.app.account.*;
import top.whysu.edevice.dto.ezviz.child.ChildTokenRequestDTO;
import top.whysu.edevice.dto.ezviz.child.ChildTokenResponseDTO;
import top.whysu.edevice.dto.ezviz.token.TokenWithAccountDTO;
import top.whysu.edevice.dto.manage.AssignAccountAddDTO;
import top.whysu.edevice.dto.system.AccountDTO;
import top.whysu.edevice.exception.AppException;
import top.whysu.edevice.exception.BusinessException;
import top.whysu.edevice.po.manage.ManageDevicePO;
import top.whysu.edevice.po.manage.ManageVoucherPO;
import top.whysu.edevice.po.relative.RelativeVoucherAccountPO;
import top.whysu.edevice.po.system.AccountPO;
import top.whysu.edevice.service.app.AppService;
import top.whysu.edevice.service.ezviz.EzvizHttpService;
import top.whysu.edevice.service.ezviz.EzvizTokenService;
import top.whysu.edevice.service.manage.ManageDeviceService;
import top.whysu.edevice.service.manage.ManageVoucherService;
import top.whysu.edevice.service.system.AccountService;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * app相关
 */
@Service("AppServiceImpl")
public class AppServiceImpl implements AppService {
    private static final Logger LOGGER = LoggerFactory.getLogger(AppServiceImpl.class);

    @Resource
    private AccountDao accountDao;
    @Resource
    private ManageVoucherDao manageVoucherDao;
    @Resource
    private AccountService accountService;
    @Resource
    private ManageVoucherService manageVoucherService;
    @Resource
    private RelativeVoucherAccountDao relativeVoucherAccountDao;
    @Resource
    private EzvizTokenService ezvizTokenService;
    @Resource
    private EzvizHttpService ezvizHttpService;
    @Resource
    private ManageDeviceService manageDeviceService;

    @Override
    public BigDecimal wholeAppRegister(AppRegisterDTO appRegisterDTO) {
        // 参数校验
        validateAppRegister(appRegisterDTO);
        // 账号是否存在
        AccountPO accountPO = accountDao.selectByUsername(appRegisterDTO.getUserName());
        if (accountPO != null) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ACCOUNT_EXIST, "账号已存在！");
        }
        // 根据邀请码获取凭证组
        ManageVoucherPO manageVoucherPO = manageVoucherDao.queryByVoucherNo(appRegisterDTO.getVoucherNo());
        if (manageVoucherPO == null) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ILLEGAL_REQUEST, "邀请码错误！");
        }
        // 创建账号，角色是访客
        AccountDTO accountDTO = new AccountDTO();
        accountDTO.setUsername(appRegisterDTO.getUserName());
        accountDTO.setRealname(appRegisterDTO.getUserName());
        accountDTO.setPassword(appRegisterDTO.getPassword());
        accountDTO.setRoleSign(DataDictionary.RoleSign.VISITOR);
        BigDecimal accountId = accountService.insertAccount(accountDTO);
        if (accountId == null) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ILLEGAL_REQUEST, "账号注册失败！");
        }

        // 添加凭证组-账号关联关系
        AssignAccountAddDTO assignAccountAddDTO = new AssignAccountAddDTO();
        assignAccountAddDTO.setUsername(appRegisterDTO.getUserName());
        assignAccountAddDTO.setVoucherId(manageVoucherPO.getId());
        manageVoucherService.wholeAddAssignAccount(assignAccountAddDTO);

        // 返回账号id
        return accountId;
    }

    @Override
    public AppLoginResponseDTO wholeLogin(AppLoginRequestDTO requestDTO) {
        if (requestDTO == null
                || StringUtils.isBlank(requestDTO.getUserName())
                || StringUtils.isBlank(requestDTO.getPwd())) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ILLEGAL_REQUEST, "参数错误，账号和密码不能为空！");
        }
        // 查询账号+密码是否正确
        Map<String, Object> params = new HashMap<>();
        params.put("username", requestDTO.getUserName());
        AccountPO accountPO = accountDao.selectOne(params);
        if (accountPO == null) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ILLEGAL_REQUEST, "账号不存在！");
        }
        String password = DigestUtil.sha256Hex(requestDTO.getPwd());
        if (!password.equals(accountPO.getPassword())) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ILLEGAL_REQUEST, "密码错误！");
        }
        // 获取当前账号的accessToken
        TokenWithAccountDTO tokenWithAccountDTO = ezvizTokenService.getChildAccountToken(accountPO.getId());
        // 响应参数
        AppLoginResponseDTO responseDTO = new AppLoginResponseDTO();
        responseDTO.setAccessToken(tokenWithAccountDTO.getChildAccessToken());
        responseDTO.setIsExpires(tokenWithAccountDTO.getExpireTime());
        responseDTO.setAppKey(tokenWithAccountDTO.getAppKey());
        responseDTO.setAppSecret(tokenWithAccountDTO.getAppSecret());
        // 查询设备集合
        List<AppDeviceInfoDTO> deviceList = null;
        List<ManageDevicePO> manageDevicePOList = manageDeviceService.getDeviceListByVoucherId(tokenWithAccountDTO.getVoucherId());
        if (CollectionUtils.isNotEmpty(manageDevicePOList)) {
            deviceList = new ArrayList<>();
            for (ManageDevicePO it : manageDevicePOList) {
                AppDeviceInfoDTO appDeviceInfoDTO = new AppDeviceInfoDTO();
                appDeviceInfoDTO.setCommDevId(it.getDeviceSerial());
                appDeviceInfoDTO.setDeviceName(it.getDeviceName());
                appDeviceInfoDTO.setDeviceType(it.getDeviceType());
                deviceList.add(appDeviceInfoDTO);
            }
        }
        responseDTO.setDeviceList(deviceList);
        return responseDTO;
    }

    @Override
    public GetAccessTokenResponseDTO getAccessToken(String username) {
        if (StringUtils.isBlank(username)) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ILLEGAL_REQUEST, "账号不能为空！");
        }
        // 查询账号+密码是否正确
        Map<String, Object> params = new HashMap<>();
        params.put("username", username);
        AccountPO accountPO = accountDao.selectOne(params);
        if (accountPO == null) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ILLEGAL_REQUEST, "账号不存在！");
        }
        // 获取当前账号的accessToken
        TokenWithAccountDTO tokenWithAccountDTO = ezvizTokenService.getChildAccountToken(accountPO.getId());
        // 响应参数
        GetAccessTokenResponseDTO responseDTO = new GetAccessTokenResponseDTO();
        responseDTO.setAccessToken(tokenWithAccountDTO.getAccessToken());
        responseDTO.setIsExpires(tokenWithAccountDTO.getExpireTime());
        responseDTO.setAppKey(tokenWithAccountDTO.getAppKey());
        responseDTO.setAppSecret(tokenWithAccountDTO.getAppSecret());
        return responseDTO;
    }

    /**
     * 参数校验
     * @param appRegisterDTO
     */
    private void validateAppRegister(AppRegisterDTO appRegisterDTO) {
        if (appRegisterDTO == null ) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ILLEGAL_REQUEST, "参数不能为空！");
        }
        if (StringUtils.isBlank(appRegisterDTO.getUserName()) || StringUtils.isBlank(appRegisterDTO.getPassword())) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ILLEGAL_REQUEST, "用户名或账号不能为空！");
        }
        if (StringUtils.isBlank(appRegisterDTO.getVoucherNo())) {
            throw new AppException(AppConstant.Code.RESULT_CODE_ILLEGAL_REQUEST, "邀请码不能为空！");
        }

    }
}
